import json
import types
from typing import Any, TextIO, BinaryIO, List, Dict, TypeVar, Tuple, Union
from io import TextIOWrapper
from pathlib import Path
from threading import Condition
import numpy as np
from torch import Tensor
import multiprocessing

ndarray = np.ndarray
V = TypeVar('V')

class JassorJsonEncoder(json.JSONEncoder):
    def __init__(self, *args, **kwargs) -> None: ...
    def encode(self, obj: Any) -> str: ...
    def iterencode(self, o, _one_shot: bool = False): ...

class IOWrapper:
    def __init__(self, write_func: callable, flush_func: callable, close_func: callable): ...

class Logger:
    STEP: int
    DEBUG: int
    INFO: int
    WARNING: int
    def __init__(self, start: int = 0, indentation: int = 1, file: TextIO | IOWrapper | TextIOWrapper | str | Path = ..., con: Condition = None, level: int = 2) -> None: ...
    def close(self) -> None: ...
    def track(self, message: str, prefix: str = ''): ...
    def step(self, message: str): ...
    def debug(self, message: str): ...
    def info(self, message: str): ...
    def warn(self, message: str): ...
    def tab(self): ...
    def __getitem__(self, item: str): ...
    def __enter__(self): ...
    def __exit__(self, exc_type: type | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None): ...

class Merger:
    def __init__(self, temp: ndarray | tuple[int, ...], kernel: ndarray | tuple[int, ...], dtype: type = ..., steep: float = 4, eps: float = 1e-17) -> None: ...
    @staticmethod
    def get_kernel(shape: tuple[int, ...], steep: float) -> ndarray: ...
    def set(self, patch: ndarray, grid: tuple[int | None, ...]) -> None: ...
    def tail(self) -> ndarray: ...

class Process(multiprocessing.Process):
    def __init__(self, target: callable, args=()) -> None: ...
    def start(self) -> None: ...
    def run(self) -> None: ...

class Queue:
    def __init__(self, maxsize: int = 0) -> None: ...
    def ready(self) -> bool: ...
    def is_end(self) -> bool: ...
    def count(self) -> int: ...
    def push(self, item: V) -> None: ...
    def top(self) -> V: ...
    def pop(self) -> V: ...
    def message(self) -> str: ...
    def end(self, flag: bool = False, message: str = '') -> None: ...

class Closed(BaseException):
    def __init__(self, message: str) -> None: ...

class QueueMessageException(BaseException):
    def __init__(self, message: str) -> None: ...
class TimerManager:
    register: dict[str, dict[str, float]]
    def __init__(self, container: str | dict[str, float] = None) -> None: ...
    def __getitem__(self, item: str): ...
    @property
    def costs(self) -> dict[str, float]: ...
    @staticmethod
    def stamp(t: float) -> str: ...
    @staticmethod
    def register_container(key: str, container: dict[str, float]): ...

class Timer:
    def __init__(self, key: str, container: str | dict[str, float]) -> None: ...
    def __enter__(self) -> None: ...
    def __exit__(self, exc_type: type | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None): ...
    def __call__(self, func: callable): ...

def random_colors(n: int, start: tuple[int, int, int] = (47, 81, 177), step: tuple[int, int, int] = (73, 119, 31), rand: tuple[int, int, int] = (10, 10, 10)) -> list[tuple[int, int, int]]: ...
def random_rainbow_curves(shape: tuple[int, int, int], s: int = 117, k: int = 7, c: int = 50): ...
def plot(item: Any, title: str = None, window_name: str = 'jassor_plot', save_to: str = None, dpi: int = 1000, ticks: bool = True): ...
def plots(items: List[Any], titles: List[str] = None, window_name: str = 'jassor_plot', save_to: str = None, dpi: int = 1000, ticks: bool = True): ...

class Table:
    def __init__(self, *dimensions: List[str] | Dict[str, str], dtype: type = object, data: ndarray = None, key_sep: str = '-', k_v_sep: str = ': ') -> Any: ...
    def __getitem__(self, items) -> Union[Table, object]: ...
    def __setitem__(self, items, value): ...
    def __str__(self) -> str: ...
    @property
    def data(self) -> ndarray: ...
    def dump(self, f: TextIO, type_repr: callable = repr): ...
    def dumpb(self, f: BinaryIO): ...
    def dumps(self, type_repr: callable = repr) -> str: ...
    @staticmethod
    def load(f: TextIO, type_loader: callable = json.loads) -> Table: ...
    @staticmethod
    def loadb(f: BinaryIO) -> Table: ...
    @staticmethod
    def loads(lines: List[str], type_loader: callable = json.loads) -> Table: ...

def uniform_iter(T_len: int, I_len: int, max_gap: int) -> List[int]: ...

def crop(image: ndarray, center: Tuple[float, float], size: Tuple[int, int], degree: float = 0, scale: float = 1, nearest: bool = True) -> ndarray: ...

class SlideWriter:
    # def __init__(self, output_path: str, tile_size: int, dimensions: tuple, spacing: float, **options: str): ...
    def __init__(self, output_path: str, tile_size: int, dimensions: tuple, mpp: float, mag: float,
        level_count: int = 5, interpolation: int = 0, channel: int = 0, dtype: type = np.uint8, **options: str): ...
    # options see:
    # color_type in ['INVALID', 'MONOCHROME', 'RGB', 'RGBA', 'INDEXED']
    # data_type in ['INVALID', 'UCHAR', 'UINT16', 'UINT32', 'FLOAT']
    # compression in ['RAW', 'JPEG', 'LZW', 'JPEG2000']
    # interpolation in ['LINEAR', 'NEAREST']
    def write(self, tile: ndarray, x: int, y: int): ...
    def finish(self): ...
    def __enter__(self): ...
    def __exit__(self, exc_type, exc_val, exc_tb): ...

def image2slide(image: ndarray, out_file: str, mpp: float = 0.5) -> None: ...

class BBox:
    XYWH = 'cxcywh'
    LURD = 'lurd'
    LUWH = 'luwh'
    def __init__(self, bbox: Union[list, ndarray, Tensor], box_format: str = LURD): ...
    @property
    def bbox(self): ...
    @property
    def contour(self): ...
    def join_region(self, l, u, r, d, eps=5): ...
    def area(self): ...
    def inter(self, bbox): ...
    def xywh(self): ...
    def lurd(self): ...
    def luwh(self): ...

def bbox_to_contour(bbox: np.ndarray): ...
def bbox_join_region(bbox: ndarray, l: float, u: float, r: float, d: float, eps: float): ...
def bbox_inter(bbox1: ndarray, bbox2: ndarray): ...
def bbox_inter_area_matrix(bbox1: ndarray, bbox2: ndarray) -> ndarray: ...
def bbox_lurd2xywh(bbox: ndarray) -> ndarray: ...
def bbox_xywh2lurd(bbox: ndarray) -> ndarray: ...
def bbox_luwh2xywh(bbox: ndarray) -> ndarray: ...
def bbox_xywh2luwh(bbox: ndarray) -> ndarray: ...
def bbox_lurd2luwh(bbox: ndarray) -> ndarray: ...
def bbox_luwh2lurd(bbox: ndarray) -> ndarray: ...

def ipynb2pycode(ipynb: str) -> str: ...

def find_contour(mask: np.ndarray): ...
